<!DOCTYPE html>
<head>
  <title>Build Failure</title>
  <meta charset="utf-8">
  <style>
    .running {
      color: #666666;
      background-color: #fffc6c;
      border-color: #c5c56d;
    }
    .completed {
      color: #ffffff;
      background-color: #8fdf5f;
      border-color: #4f8530;
    }
    .error {
      color: #ffffff;
      background-color: #e98080;
      border-color: #a77272;
    }
    table {
      border-collapse: collapse;
      border: 1px solid gray;
    }
    table td, th {
      border: 1px solid gray;
    }
    .thumbs-up-down {
      border-radius: 7px;
      display: inline-block;
      height: 28px;
    }
    .triage, .triaged {
      display: block;
      float: left;
      vertical-align: middle;
    }
    .triage {
      background-color: #e5e5e5;
      cursor: pointer;
    }
    .triaged {
      cursor: default;
    }
    .thumb-up {
      border-top: solid 1px;
      border-bottom: solid 1px;
      border-left: solid 1px;
      border-top-left-radius: 7px;
      border-bottom-left-radius: 7px;
      padding-left: 10px;
      padding-right: 10px;
    }
    .thumb-down {
      border: solid 1px;
      border-top-right-radius: 7px;
      border-bottom-right-radius: 7px;
      padding-left: 10px;
      padding-right: 10px;
    }
    .thumb-up:hover, .thumb-up.triaged {
      background-color: #8fdf5f;
    }
    .thumb-down:hover, .thumb-down.triaged {
      background-color: #e98080;
    }
  </style>
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/themes/smoothness/jquery-ui.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
  <script>
    analysisCompleted = '{{analysis_completed}}' == 'True';
    analysisFailed = '{{analysis_failed}}' == 'True';
    build_url = 'https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{build_number}}';
    analysisCorrect = '{{analysis_correct}}';  // Possible values: 'None', 'True', or 'False'.

    function TriageAnalysisResult(e) {
      var target = $(this);
      if (target.hasClass('triaged'))
        return;

      var correct = target.hasClass('thumb-up');
      $.getJSON('triage-analysis?correct=' + correct + '&url=' + build_url, function(data) {
        if (data['success']) {
          $('.triaged').addClass('triage').removeClass('triaged');
          target.addClass('triaged').removeClass('triage');
        } else {
          alert('Failed to update datastore. Please refresh and try again.');
        }
      }).error(function(xhr) {
        // Replace the whole page with errors from server side.
        document.body.outerHTML = xhr.responseText;
      });

      e.preventDefault();
    }

    $(document).ready(function() {
      if (!analysisCompleted) {
        $('#status_message').text('running, will refresh in 5 seconds...');
        $('#status_message').attr('class', 'running');
        setTimeout(function(){
          {% if show_debug_info %}
          window.location.href = 'build-failure?url=' + build_url + '&debug=1';
          {% else %}
          window.location.href = 'build-failure?url=' + build_url;
          {% endif %}
        }, 5000);
      } else if (analysisFailed) {
        $('#status_message').text('error');
        $('#status_message').attr('class', 'error');
      } else {
        // TODO: use another style when no culprit CL is found.
        $('#status_message').text('completed');
        $('#status_message').attr('class', 'completed');

        $('.triage').click(TriageAnalysisResult);

        if (analysisCorrect == 'True') {
          $('.thumb-up').addClass('triaged').removeClass('triage');
        } else if (analysisCorrect == 'False') {
          $('.thumb-down').addClass('triaged').removeClass('triage');
        }
      }

      $('#score-explanation-dialog').dialog({
        autoOpen: false,
        modal: true,
        width: 600,
      });
      $('#score-info').click(function() {
        $('#score-explanation-dialog').dialog('open');
      });
    });
  </script>
</head>
<body>
  Findit is in alpha version. (<a href="https://code.google.com/p/chromium/issues/entry?status=Unconfirmed&labels=Pri-2,findit&summary=Findit%20bug%20or%20reature%20request&comment=Url%20to%20the%20build%20Failure:%0Ahttps://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{build_number}}%0A%0AWhat%20is%20the%20bug%20or%20feature:%0A">File a Findit bug</a>)
  <br>
  <br>

  <b>Build info:</b>
  <div>
    Master: {{master_name}}<br>
    Builder: <a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}">{{builder_name}}</a><br>
    Build Number: <a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{build_number}}">{{build_number}}</a>
  </div>
  <br>

  <b>Analysis info:</b>
  <div id="analysis_info">
    status: <span id="status_message"></span>
  {% if show_debug_info %}
    {% if pipeline_status_path %}
      <a href="{{pipeline_status_path}}">pipeline</a>
    {% endif %}
    <br>
    Requested: {{analysis_requested | default('N/A', true)}}<br>
    Started: {{analysis_started | default('N/A', true)}}<br>
    Updated: {{analysis_updated}}<br>
  {% endif %}
  </div>
  <br>

  {% if analysis_completed %}
  <b>Analysis result:</b>
    {% if analysis_failed %}
      <br>
      <span class="error">No result because of some error in analysis!</span>
    {% elif analysis_result.failures|length == 0 %}
      <div>No failure is found.</div>
    {% else %}
      <div class="thumbs-up-down">
        <div class="triage thumb-up">Correct <img src="https://www.gstatic.com/images/icons/material/system/1x/thumb_up_black_24dp.png"/></div>
        <div class="triage thumb-down"><img src="https://www.gstatic.com/images/icons/material/system/1x/thumb_down_black_24dp.png"/> Incorrect</div>
      </div>
      <div id="analysis_result">
        <table id="failures">
          <tr>
            <th rowspan="2" title="Failed step name">Step</th>
            <th rowspan="2" title="The build cycle in which the step started to fail">First Failure</th>
            <th rowspan="2" title="The last build cycle in which the step passed">Last Pass<br>Before Failure</th>
            <th colspan="7">Suspected CLs</th>
          </tr>
          <tr>
            <th title="The build cycle in which the CL was built or tested for the first time">Build Number</th>
            <th title="The Git repo name of the CL">Repo Name</th>
            <th title="Git commit position/hash">Commit</th>
            <th title="The higher score, the more suspected">Score (<a id="score-info" href="javascript:">?</a>)</th>
            <th title="Why this CL is related to the failure">Hints</th>
          </tr>
          <tbody>
          {% for failure in analysis_result.failures %}
            {% if failure.suspected_cls|length == 0 %}
              <tr>
                <td>
                {% if show_debug_info %}
                  <a href="./failure-log?url=https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{build_number}}/steps/{{failure.step_name}}">{{failure.step_name}}</a>
                {% else %}
                  <a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{build_number}}/steps/{{failure.step_name}}">{{failure.step_name}}</a>
                {% endif %}
                </td>
                <td><a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{failure.first_failure}}">{{failure.first_failure}}</a></td>
                {% if failure.last_pass %}
                <td><a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{failure.last_pass}}">{{failure.last_pass}}</a></td>
                {% else %}
                <td>N/A</td>
                {% endif %}
                <td colspan="5">Not found.</td>
              </tr>
            {% else %}
              {% set first_suspected_cl = failure.suspected_cls[0] %}
              <tr>
                <td rowspan="{{failure.suspected_cls|length}}">
                {% if show_debug_info %}
                  <a href="./failure-log?url=https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{build_number}}/steps/{{failure.step_name}}">{{failure.step_name}}</a>
                {% else %}
                  <a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{build_number}}/steps/{{failure.step_name}}">{{failure.step_name}}</a>
                {% endif %}
                </td>
                <td rowspan="{{failure.suspected_cls|length}}"><a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{failure.first_failure}}">{{failure.first_failure}}</a></td>
                {% if failure.last_pass %}
                <td rowspan="{{failure.suspected_cls|length}}"><a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{failure.last_pass}}">{{failure.last_pass}}</a></td>
                {% else %}
                <td rowspan="{{failure.suspected_cls|length}}">N/A</td>
                {% endif %}

                <td><a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{first_suspected_cl.build_number}}">{{first_suspected_cl.build_number}}</a></td>
                <td>{{first_suspected_cl.repo_name}}</td>
                <td>
                  {% if first_suspected_cl.commit_position %}
                    <a href="{{first_suspected_cl.url}}">{{first_suspected_cl.commit_position}}</a>
                  {% else %}
                    <a href="{{first_suspected_cl.url}}">{{first_suspected_cl.revision}}</a>
                  {% endif %}
                </td>
                <td>{{first_suspected_cl.score}}</td>
                <td>
                  {% for hint, _ in first_suspected_cl.hints|dictsort(case_sensitive=True, by='value')|reverse %}
                    <li>{{hint}}</li>
                  {% endfor %}
                </td>
              </tr>
              {# Show the remaining suspected CLs, so skip the first three columns. #}
              {% for suspected_cl in failure.suspected_cls[1:] %}
              <tr>
                <td><a href="https://build.chromium.org/p/{{master_name}}/builders/{{builder_name}}/builds/{{suspected_cl.build_number}}">{{suspected_cl.build_number}}</a></td>
                <td>{{suspected_cl.repo_name}}</td>
                <td>
                  {% if suspected_cl.commit_position %}
                    <a href="{{suspected_cl.url}}">{{suspected_cl.commit_position}}</a>
                  {% else %}
                    <a href="{{suspected_cl.url}}">{{suspected_cl.revision}}</a>
                  {% endif %}
                </td>
                <td>{{suspected_cl.score}}</td>
                <td>
                  {% for hint, _ in suspected_cl.hints|dictsort(case_sensitive=True, by='value')|reverse %}
                    <li>{{hint}}</li>
                  {% endfor %}
                </td>
              </tr>
              {% endfor %}
            {% endif %}
          {% endfor %}
          </tbody>
      </div>
    {% endif %}
  {% endif %}
  <div id="score-explanation-dialog" title="Score Explanation">
    The total score is a sum of scores for all hints.<br>
    Rules to set a score to an hint:
    <ul>
      <li>5: The CL added or deleted a file that appears in the failure log.</li>
      <li>2: The CL modified a file that appears in the failure log.</li>
      <li>1: The CL modified a file that is related to another file
             appearing in the failure log. (eg: file.h was changed and
             file_unittest.cc or file_impl.cc appeared in the log.)</li>
      <li>1: The CL rolled a dependency within src/DEPS and a file of that
             dependency appears in the failure log. (eg: third_party/dep
             was changed in src/DEPS and third_party/dep/f.cpp appeared
             in the log.)</li>
    </ul>
    (More rules will be added when implemented.)
  </div>
</body>
